package com.gec.realms;

import com.gec.dao.RoleDao;
import com.gec.dao.UserDao;
import com.gec.domain.Role;
import com.gec.domain.User;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.HashSet;
import java.util.Set;


//{1}AuthorizingRealm [做认证 + 授权]
//{2}AuthenticatingRealm [只做认证]

public class MyAuthorizationRealm extends AuthorizingRealm {

    //{1}自动装配两个属性
    private final UserDao userDao;
    private final RoleDao roleDao;

    public MyAuthorizationRealm(UserDao userDao, RoleDao roleDao) {
        this.userDao = userDao;
        this.roleDao = roleDao;
    }

    //{1}哪个有 Token(令牌)哪个就是认证。(登录)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        //{1}先拿到 account
        String account = (String) token.getPrincipal();
        //{2}去数据库获取 user [连角色一起拿]
        User user = userDao.getUserByAccount(
                account);
        //{3}如果 user==null, 直接返回 null.
        if (user == null) {
            return null; //到时认证器自动抛出一个异常
        }
        //{4}以后有可能在这里做加密(加盐)处理
        //----------
        //{5}创建一个简单认证信息类
        //   令牌中的密码不用获取, 有人会帮你比对。
        //   你只要数据库的密码传入即可。
        AuthenticationInfo info = new SimpleAuthenticationInfo(
                user, user.getPassword(), getName());
        //{6}返回信息类。
        return info;
    }

    //{2}这个方法是授权方法。
    //   写这个方法的目的:
    //   1. 从数据库中取出用户所持有的角色  or 权限数据
    //   2. 封装到一个授权信息类中。
    //   3. 给到 【授权器】来做 【鉴权】 判定。
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principals) {
        //1. 获取用户主身份信息
        User user = (User) principals.getPrimaryPrincipal();
        //2. 获取该用户有哪些角色
        Role role = user.getPrimaryRole();
        HashSet<String> _roles = new HashSet<>();
        _roles.add(role.getRoleName());
        //3. 获取该用户有哪些权限
        String roleId = role.getId();
        Set<String> perms = roleDao.getRolePermission(roleId);
        //这些权限是什么: [user:viewList, user:edit]
        //4. 封装角色到授权信息类中
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(_roles);
        //5. 封装权限到授权信息类中(多个权限信息)
        info.addStringPermissions(perms);
        //6. 给到 【授权器】来做 【鉴权】 判定。
        return info;
    }

}
